﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Services.Client;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Samples.ServiceHosting.StorageClient;
using TweetPollDataService;

namespace TwitterPoll_WebRole
{
    public partial class _Default : System.Web.UI.Page
    {
        private class TweetCountPoint
        {
            public int NumberOfChars { get; set; }
            public int Count { get; set; }
        }
        

        protected void Page_Load(object sender, EventArgs e)
        {
            List<TweetCountPoint> tweetCountPoints = new List<TweetCountPoint>(); //Will store the returned list of tweet length counters.

            GetTweetCountsFromAzureTableStorage(ref tweetCountPoints);

            DisplayGraphOfTweetCounts(tweetCountPoints);

            DisplayTotalNumberOfPolledTweets(tweetCountPoints);

            DisplayHeadOfAzureQueue("tweetpoll");

            DisplayPageLoadCount();
        }

        private void DisplayTotalNumberOfPolledTweets(List<TweetCountPoint> tweetCountPoints)
        {
            txtTotalTweets.Text = ((tweetCountPoints.Select(i => i.Count)).Sum()).ToString();
        }

        private void GetTweetCountsFromAzureTableStorage(ref List<TweetCountPoint> tweetCountPoints)
        {
            StorageAccountInfo tableAccount = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
            TweetPollDataServiceContext svc = new TweetPollDataServiceContext(tableAccount);

            var resultQuery = from row in svc.Table
                              where row.PartitionKey == "tweetLengthCount"
                              //orderby row.RowKey ascending 
                              select row;
            
            TableStorageDataServiceQuery<TweetPollEntity> query = new TableStorageDataServiceQuery<TweetPollEntity>(resultQuery as DataServiceQuery<TweetPollEntity>, svc.RetryPolicy);
            IEnumerable<TweetPollEntity> results = query.ExecuteAllWithRetries();
            tweetCountPoints = (results.Select(
                r => new TweetCountPoint
                         {
                             NumberOfChars = Convert.ToInt32(r.RowKey), 
                             Count = r.Count
                         }
                )
                               ).OrderBy(t => t.NumberOfChars).ToList();
        }

        private void DisplayGraphOfTweetCounts(List<TweetCountPoint> tweetCountPoints)
        {
            String scriptString = "<script language=\"JavaScript\"> var arr = [ ";
            for (int i = 0; i < tweetCountPoints.Count; i++)
            {
                scriptString += "[" + tweetCountPoints[i].NumberOfChars.ToString() + "," +
                                tweetCountPoints[i].Count.ToString() + "]";
                if (i < tweetCountPoints.Count - 1)
                {
                    scriptString += ", ";
                }
            }
            scriptString += " ]; ";
            scriptString += @"$(function() {$.plot($(""#placeholder""), [arr]);});";
            scriptString += "</script>";
            this.ClientScript.RegisterStartupScript(this.Page.GetType(), "Startup", scriptString);
        }

        private void DisplayHeadOfAzureQueue(string queueName)
        {
            bool exists;
            //Step 1: Peek (but not get) messages from the head of the queue (max allowed is 32)
            StorageAccountInfo queueAccount = StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();
            QueueStorage queueService = QueueStorage.Create(queueAccount);
            queueService.RetryPolicy = RetryPolicies.RetryN(2, TimeSpan.FromMilliseconds(100));
            MessageQueue q = queueService.GetQueue(queueName);
            q.CreateQueue(out exists);
            IEnumerable<Message> messages = q.PeekMessages(32); //PeekMessages() enables you to look at queue contents without taking anything off the queue

            DataTable dt = new DataTable();
            DataRow dr;
            dt.Columns.Add(new DataColumn( "Tweeter", typeof(string)));
            dt.Columns.Add(new DataColumn( "Message", typeof(string)));
            if (messages != null)
                foreach (var msg in messages)
                {
                    XElement el = XElement.Parse(msg.ContentAsString(), LoadOptions.PreserveWhitespace);
                    dr = dt.NewRow();
                    string tweeter = String.Format("http://twitter.com/{0}", el.Element("user").Element("screen_name").Value.ToString());
                    dr["Tweeter"] = tweeter;
                    dr["Message"] = el.Element("text").Value.ToString();

                    dt.Rows.Add(dr);
                }


            var dg = this.CurrentTweetsOnQueue;
            dg.Columns.Clear();
            dg.DataSource = new DataView(dt);
            dg.DataBind();
        }

        private void DisplayPageLoadCount()
        {
            const string PartitionKey = "tweetpollpageaccessedcount";
            StorageAccountInfo tableAccount = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
            TweetPollDataServiceContext svc = new TweetPollDataServiceContext(tableAccount);

            //Does a counter already exist for the pagecount
            var resultQuery = from row in svc.Table
                              where row.PartitionKey == PartitionKey
                              select row;

            TableStorageDataServiceQuery<TweetPollEntity> query = new TableStorageDataServiceQuery<TweetPollEntity>(resultQuery as DataServiceQuery<TweetPollEntity>, svc.RetryPolicy);
            IEnumerable<TweetPollEntity> results = query.ExecuteAllWithRetries();
            if (results.Count() == 0)
            {
                //add a new entity (i.e. row)
                svc.AddObject(TweetPollDataServiceContext.TableName, new TweetPollEntity(PartitionKey, "home", 1));
                this.txtPageLoadCount.Text = 1.ToString();
            }
            else
            {
                //or increment existing
                var entity = results.SingleOrDefault();
                entity.Count = ++entity.Count;
                svc.UpdateObject(entity);
                this.txtPageLoadCount.Text = entity.Count.ToString();
            }
            svc.SaveChangesWithRetries();
        }
    }
}
